﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using MedicalManagementSystem.Utils;

namespace MedicalManagementSystem.Models
{
    public partial class Patient : IValidatable
    {
        public PatientChart CurrentChart
        {
            get
            {
                return this.Do(p => p.LoadPatientChart()).PatientChart
                    .Where(ch => ch.DateArrive <= DateTime.Now && !ch.DateLeave.HasValue)
                    .FirstOrDefault();
            }
        }

        public string Initials
        {
            get { return string.Format("{0} {1} {2}", Surname, Name, Patronymic); }
        }

        public static Patient GetByPK(int id)
        {
            return DbContext.Instance.Patient.Where(person => person.id == id).FirstOrDefault();
        }

        public void Load()
        {
            if (EntityState != System.Data.EntityState.Added && EntityState != System.Data.EntityState.Detached)
            {
                if (!this.AddressReference.IsLoaded)
                {
                    AddressReference.Load();
                }
                if (!this.DisabilityReference.IsLoaded)
                {
                    DisabilityReference.Load();
                }
                LoadPatientChart();
            }
        }

        public void LoadPatientChart()
        {
            if (EntityState != System.Data.EntityState.Added && EntityState != System.Data.EntityState.Detached)
            {
                if (!PatientChart.IsLoaded)
                {
                    PatientChart.Load();
                }
            }
        }

        public bool CheckBeforeSave()
        {
            return GetRuleViolations().Count() == 0;
        }

        public IEnumerable<IRuleViolation> GetRuleViolations()
        {
            if (string.IsNullOrEmpty(Surname))
            {
                yield return new RuleViolation("Необходимо заполнить фамилию пациента.", this, "Surname", Surname);
            }
            if (string.IsNullOrEmpty(Name))
            {
                yield return new RuleViolation("Необходимо заполнить имя пациента.", this, "Name", Name);
            }
            if (string.IsNullOrEmpty(Patronymic))
            {
                yield return new RuleViolation("Необходимо заполнить отчество пациента.", this, "Patronymic", Patronymic);
            }
            if (Birthday == DateTime.MinValue)
            {
                yield return new RuleViolation("Неверный формат даты.", this, "Birthday", Birthday);
            }
            if (string.IsNullOrEmpty(CardName))
            {
                yield return new RuleViolation("Необходимо заполнить номер карточки.", this, "CardName", CardName);
            }
        }

        public static IEnumerable<Patient> CurrentPatients
        {
            get
            {
                return DbContext.Instance.PatientChart
                .Where(pch => pch.DateArrive <= DateTime.Now && pch.DateLeave == null)
                .ToList()
                .Each(pch => pch.LoadPatient())
                .Select(pch => pch.Patient)
                .Distinct();
            }
        }

        #region Find Patients

        public static IEnumerable<Patient> SearchPatient(string pattern)
        {
            return SearchPatient(DbContext.Instance.Patient, pattern);
        }

        public static IEnumerable<Patient> SearchPatient(IEnumerable<Patient> patients, string pattern)
        {
            var searchStrings = pattern
                .Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)
                .Take(3).ToArray();

            var initials = new string[3];
            {
                int i = 0;
                foreach (var searchString in searchStrings)
                {
                    initials[i++] = searchString;
                }
                for (; i < initials.Count(); i++)
                {
                    initials[i] = string.Empty;
                }
            }
            return SearchPatient(patients, initials[0], initials[1], initials[2]);
        }

        public static IEnumerable<Patient> SearchPatient(string surname, string name, string patronymic)
        {
            return SearchPatient(DbContext.Instance.Patient, surname, name, patronymic);
        }

        public static IEnumerable<Patient> SearchPatient(IEnumerable<Patient> patients, string surname, string name)
        {
            return SearchPatient(patients, surname, name, string.Empty);
        }

        public static IEnumerable<Patient> SearchPatient(IEnumerable<Patient> patients, string surname, string name, string patronymic)
        {
            surname = surname.ToLower();
            name = name.ToLower();
            patronymic = patronymic.ToLower();
            return patients.Where(
                p =>
                    p.Surname.ToLower().Contains(surname) &&
                    p.Name.ToLower().Contains(name) &&
                    p.Patronymic.ToLower().Contains(patronymic))

                .OrderBy(p => p.Surname.ToLower().IndexOf(surname))
                .ThenBy(p => p.Name.ToLower().IndexOf(name))
                .ThenBy(p => p.Patronymic.ToLower().IndexOf(patronymic))

                .ThenBy(p => p.Surname)
                .ThenBy(p => p.Name)
                .ThenBy(p => p.Patronymic);

        }

        public static IEnumerable<Patient> SortPatients(IEnumerable<Patient> patients)
        {
            return patients.OrderBy(p => p.Surname)
                           .ThenBy(p => p.Name)
                           .ThenBy(p => p.Patronymic);
        }

        public static IEnumerable<Patient> SortedPatients
        {
            get { return SortPatients(DbContext.Instance.Patient); }
        }

        #endregion

        public override string ToString()
        {
            return string.Format(string.Format("{0} {1} {2} {3:d}", Surname, Name, Patronymic, Birthday));
        }
    }
}
